home *** CD-ROM | disk | FTP | other *** search
/ Programming an RTS Game with Direct3D / Programming an RTS Game with Direct3D.iso / Examples / Chapter 5 / Example 5.5 / app.cpp next >
Encoding:
C/C++ Source or Header  |  2006-08-01  |  9.7 KB  |  370 lines

  1. //////////////////////////////////////////////////////////////
  2. // Example 5.5: Viewport Rendering                            //
  3. // Written by: C. Granberg, 2006                            //
  4. //////////////////////////////////////////////////////////////
  5.  
  6. #include <windows.h>
  7. #include <d3dx9.h>
  8. #include "debug.h"
  9. #include "mesh.h"
  10. #include "object.h"
  11. #include "camera.h"
  12.  
  13. class APPLICATION
  14. {
  15.     public:
  16.         APPLICATION();
  17.         HRESULT Init(HINSTANCE hInstance, int width, int height, bool windowed);
  18.         HRESULT Update(float deltaTime);
  19.         HRESULT Render();
  20.         HRESULT Cleanup();
  21.         HRESULT Quit();
  22.  
  23.     private:
  24.         IDirect3DDevice9* m_pDevice; 
  25.         MESH *m_pTrack;
  26.         std::vector<OBJECT> m_cars;
  27.  
  28.         D3DLIGHT9 m_light;
  29.         D3DRECT m_destRects[2];
  30.         D3DRECT m_srcRects[2];
  31.         D3DRECT m_currentRects[2];
  32.  
  33.         int m_viewConfig;
  34.         float m_viewPortPrc;
  35.         HWND m_mainWindow;
  36.         ID3DXFont *m_pFont;
  37. };
  38.  
  39. int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE prevInstance, PSTR cmdLine, int showCmd)
  40. {
  41.     APPLICATION app;
  42.  
  43.     if(FAILED(app.Init(hInstance, 800, 600, true)))
  44.         return 0;
  45.  
  46.     MSG msg;
  47.     memset(&msg, 0, sizeof(MSG));
  48.     int startTime = timeGetTime(); 
  49.  
  50.     while(msg.message != WM_QUIT)
  51.     {
  52.         if(::PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
  53.         {
  54.             ::TranslateMessage(&msg);
  55.             ::DispatchMessage(&msg);
  56.         }
  57.         else
  58.         {    
  59.             int t = timeGetTime();
  60.             float deltaTime = (t - startTime)*0.001f;
  61.  
  62.             app.Update(deltaTime);
  63.             app.Render();
  64.  
  65.             startTime = t;
  66.         }
  67.     }
  68.  
  69.     app.Cleanup();
  70.  
  71.     return msg.wParam;
  72. }
  73.  
  74. APPLICATION::APPLICATION()
  75. {
  76.     m_pDevice = NULL; 
  77.     m_mainWindow = 0;
  78.     m_pTrack = NULL;
  79.     m_viewConfig = 0;
  80.     m_viewPortPrc = 0.0f;
  81.  
  82.     //Setup viewports
  83.     m_srcRects[0].x1 = 5;
  84.     m_srcRects[0].x2 = 395;
  85.     m_srcRects[0].y1 = 35;
  86.     m_srcRects[0].y2 = 595;
  87.  
  88.     m_srcRects[1].x1 = 405;
  89.     m_srcRects[1].x2 = 795;
  90.     m_srcRects[1].y1 = 35;
  91.     m_srcRects[1].y2 = 595;
  92.  
  93.     m_currentRects[0] = m_destRects[0] = m_srcRects[0];
  94.     m_currentRects[0] = m_destRects[1] = m_srcRects[1];
  95.  
  96.     srand(GetTickCount());
  97. }
  98.  
  99. HRESULT APPLICATION::Init(HINSTANCE hInstance, int width, int height, bool windowed)
  100. {
  101.     debug.Print("Application initiated");
  102.  
  103.     //Create Window Class
  104.     WNDCLASS wc;
  105.     memset(&wc, 0, sizeof(WNDCLASS));
  106.     wc.style         = CS_HREDRAW | CS_VREDRAW;
  107.     wc.lpfnWndProc   = (WNDPROC)::DefWindowProc; 
  108.     wc.hInstance     = hInstance;
  109.     wc.lpszClassName = "D3DWND";
  110.  
  111.     //Register Class and Create new Window
  112.     RegisterClass(&wc);
  113.     m_mainWindow = CreateWindow("D3DWND", "Example 5.5: Viewport Rendering", WS_EX_TOPMOST, 0, 0, width, height, 0, 0, hInstance, 0); 
  114.     SetCursor(NULL);
  115.     ShowWindow(m_mainWindow, SW_SHOW);
  116.     UpdateWindow(m_mainWindow);
  117.  
  118.     //Create IDirect3D9 Interface
  119.     IDirect3D9* d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
  120.  
  121.     if(d3d9 == NULL)
  122.     {
  123.         debug.Print("Direct3DCreate9() - FAILED");
  124.         return E_FAIL;
  125.     }
  126.  
  127.     //Check that the Device supports what we need from it
  128.     D3DCAPS9 caps;
  129.     d3d9->GetDeviceCaps(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &caps);
  130.  
  131.     //Hardware Vertex Processing or not?
  132.     int vp = 0;
  133.     if(caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT)
  134.         vp = D3DCREATE_HARDWARE_VERTEXPROCESSING;
  135.     else vp = D3DCREATE_SOFTWARE_VERTEXPROCESSING;
  136.  
  137.     //Check vertex & pixelshader versions
  138.     if(caps.VertexShaderVersion < D3DVS_VERSION(2, 0) || caps.PixelShaderVersion < D3DPS_VERSION(2, 0))
  139.     {
  140.         debug.Print("Warning - Your graphic card does not support vertex and pixelshaders version 2.0");
  141.     }
  142.  
  143.     //Set D3DPRESENT_PARAMETERS
  144.     D3DPRESENT_PARAMETERS d3dpp;
  145.     d3dpp.BackBufferWidth            = width;
  146.     d3dpp.BackBufferHeight           = height;
  147.     d3dpp.BackBufferFormat           = D3DFMT_A8R8G8B8;
  148.     d3dpp.BackBufferCount            = 1;
  149.     d3dpp.MultiSampleType            = D3DMULTISAMPLE_NONE;
  150.     d3dpp.MultiSampleQuality         = 0;
  151.     d3dpp.SwapEffect                 = D3DSWAPEFFECT_DISCARD; 
  152.     d3dpp.hDeviceWindow              = m_mainWindow;
  153.     d3dpp.Windowed                   = windowed;
  154.     d3dpp.EnableAutoDepthStencil     = true; 
  155.     d3dpp.AutoDepthStencilFormat     = D3DFMT_D24S8;
  156.     d3dpp.Flags                      = 0;
  157.     d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;
  158.     d3dpp.PresentationInterval       = D3DPRESENT_INTERVAL_IMMEDIATE;
  159.  
  160.     //Create the IDirect3DDevice9
  161.     if(FAILED(d3d9->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, m_mainWindow,
  162.                                  vp, &d3dpp, &m_pDevice)))
  163.     {
  164.         debug.Print("Failed to create IDirect3DDevice9");
  165.         return E_FAIL;
  166.     }
  167.  
  168.     //Release IDirect3D9 interface
  169.     d3d9->Release();
  170.  
  171.     D3DXCreateFont(m_pDevice, 18, 0, 0, 1, false,  
  172.                    DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, DEFAULT_QUALITY,
  173.                    DEFAULT_PITCH | FF_DONTCARE, "Arial", &m_pFont);
  174.  
  175.     //Load objects
  176.     LoadObjectResources(m_pDevice);
  177.  
  178.     m_pTrack = new MESH("objects/track.x", m_pDevice);
  179.     m_cars.push_back(OBJECT(0, D3DXVECTOR3(0.0f, 0.0f, 0.5f), D3DXVECTOR3(0.0f, 0.0f, 0.0f), 1.6f));
  180.     m_cars.push_back(OBJECT(1, D3DXVECTOR3(0.0f, 0.0f, -1.5f), D3DXVECTOR3(0.0f, 0.0f, 0.0f), -1.6f));
  181.     m_cars[1].m_activeCam = 1;
  182.  
  183.     //Create m_light
  184.     ::ZeroMemory(&m_light, sizeof(m_light));
  185.     m_light.Type      = D3DLIGHT_DIRECTIONAL;
  186.     m_light.Ambient   = D3DXCOLOR(0.5, 0.5, 0.5, 1.0f);
  187.     m_light.Diffuse   = D3DXCOLOR(0.9, 0.9, 0.9, 1.0f);
  188.     m_light.Specular  = D3DXCOLOR(0.5, 0.5, 0.5, 1.0f);
  189.     m_light.Direction = D3DXVECTOR3(0.5f, -0.6f, 0.0f);
  190.     m_pDevice->SetLight(0, &m_light);
  191.     m_pDevice->LightEnable(0, true);
  192.  
  193.     //Set sampler state
  194.     for(int i=0;i<4;i++)
  195.     {
  196.         m_pDevice->SetSamplerState(i, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
  197.         m_pDevice->SetSamplerState(i, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
  198.         m_pDevice->SetSamplerState(i, D3DSAMP_MIPFILTER, D3DTEXF_POINT);
  199.     }
  200.  
  201.     return S_OK;
  202. }
  203.  
  204. HRESULT APPLICATION::Update(float deltaTime)
  205. {
  206.     //Control camera
  207.     D3DXMATRIX  matWorld;
  208.     D3DXMatrixIdentity(&matWorld);
  209.     m_pDevice->SetTransform(D3DTS_WORLD, &matWorld);
  210.  
  211.     for(int i=0;i<m_cars.size();i++)
  212.         m_cars[i].Update(deltaTime);
  213.  
  214.     if(KEYDOWN(VK_F1))        //Change Camera 1
  215.     {
  216.         m_cars[0].m_activeCam++;
  217.         if(m_cars[0].m_activeCam >= m_cars[0].m_cameras.size())
  218.             m_cars[0].m_activeCam = 0;
  219.         Sleep(300);
  220.     }
  221.     else if(KEYDOWN(VK_F2))    //Change Camera 2
  222.     {
  223.         m_cars[1].m_activeCam++;
  224.         if(m_cars[1].m_activeCam >= m_cars[0].m_cameras.size())
  225.             m_cars[1].m_activeCam = 0;
  226.         Sleep(300);
  227.     }
  228.     else if(KEYDOWN(VK_SPACE))        //Change Viewport settings
  229.     {
  230.         m_viewConfig++;
  231.         if(m_viewConfig >= 3)
  232.             m_viewConfig = 0;
  233.  
  234.         if(m_viewConfig == 0)        //Split X
  235.         {
  236.             m_destRects[0].x1 = 5;
  237.             m_destRects[0].x2 = 395;
  238.             m_destRects[0].y1 = 35;
  239.             m_destRects[0].y2 = 595;
  240.             m_destRects[1].x1 = 405;
  241.             m_destRects[1].x2 = 795;
  242.             m_destRects[1].y1 = 35;
  243.             m_destRects[1].y2 = 595;
  244.         }
  245.         else if(m_viewConfig == 1)        //Split Y
  246.         {
  247.             m_destRects[0].x1 = 5;
  248.             m_destRects[0].x2 = 795;
  249.             m_destRects[0].y1 = 35;
  250.             m_destRects[0].y2 = 305;
  251.             m_destRects[1].x1 = 5;
  252.             m_destRects[1].x2 = 795;
  253.             m_destRects[1].y1 = 325;
  254.             m_destRects[1].y2 = 595;
  255.         }
  256.         else if(m_viewConfig == 2)        //Big 1, Small 2
  257.         {
  258.             m_destRects[0].x1 = 30;
  259.             m_destRects[0].x2 = 770;
  260.             m_destRects[0].y1 = 60;
  261.             m_destRects[0].y2 = 570;
  262.             m_destRects[1].x1 = 650;
  263.             m_destRects[1].x2 = 790;
  264.             m_destRects[1].y1 = 35;
  265.             m_destRects[1].y2 = 175;
  266.         }
  267.  
  268.         m_viewPortPrc = 0.0f;
  269.         m_srcRects[0] = m_currentRects[0];
  270.         m_srcRects[1] = m_currentRects[1];
  271.         Sleep(300);
  272.     }
  273.     else if(KEYDOWN(VK_ESCAPE))
  274.         Quit();
  275.  
  276.     //Change viewport rectangles
  277.     m_viewPortPrc += deltaTime;
  278.     if(m_viewPortPrc > 1.0f)m_viewPortPrc = 1.0f;
  279.  
  280.     //Linear interpolation between the two rectangles
  281.     for(int i=0;i<2;i++)
  282.     {
  283.         m_currentRects[i].x1 = m_srcRects[i].x1 - (m_srcRects[i].x1*m_viewPortPrc) + (m_destRects[i].x1*m_viewPortPrc);
  284.         m_currentRects[i].x2 = m_srcRects[i].x2 - (m_srcRects[i].x2*m_viewPortPrc) + (m_destRects[i].x2*m_viewPortPrc);
  285.         m_currentRects[i].y1 = m_srcRects[i].y1 - (m_srcRects[i].y1*m_viewPortPrc) + (m_destRects[i].y1*m_viewPortPrc);
  286.         m_currentRects[i].y2 = m_srcRects[i].y2 - (m_srcRects[i].y2*m_viewPortPrc) + (m_destRects[i].y2*m_viewPortPrc);
  287.     }
  288.  
  289.     return S_OK;
  290. }    
  291.  
  292. HRESULT APPLICATION::Render()
  293. {
  294.     // Clear the viewport
  295.     D3DVIEWPORT9 v;
  296.     v.X = v.Y = 0;
  297.     v.Width = 800;
  298.     v.Height = 600;
  299.     v.MaxZ = 1.0f;
  300.     v.MinZ = 0.0f;
  301.  
  302.     m_pDevice->SetViewport(&v);
  303.  
  304.     m_pDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0x00000000, 1.0f, 0L );
  305.  
  306.     RECT r[] = {{340, 10, 0, 0}, {40, 10, 0, 0}, {640, 10, 0, 0}};
  307.     m_pFont->DrawText(NULL, "Space: Viewport", -1, &r[0], DT_LEFT| DT_TOP | DT_NOCLIP, 0xffffffff);
  308.     m_pFont->DrawText(NULL, "F1: Camera 1", -1, &r[1], DT_LEFT| DT_TOP | DT_NOCLIP, 0xffffffff);
  309.     m_pFont->DrawText(NULL, "F2: Camera 2", -1, &r[2], DT_LEFT| DT_TOP | DT_NOCLIP, 0xffffffff);
  310.  
  311.     // Begin the scene 
  312.     if(SUCCEEDED(m_pDevice->BeginScene()))
  313.     {
  314.         //For each car
  315.         for(int c=0;c<m_cars.size();c++)
  316.         {
  317.             //Set and clear viewport
  318.             v.X = m_currentRects[c].x1;
  319.             v.Y = m_currentRects[c].y1;
  320.             v.Width = m_currentRects[c].x2 - m_currentRects[c].x1;
  321.             v.Height = m_currentRects[c].y2 - m_currentRects[c].y1;            
  322.             m_pDevice->SetViewport(&v);
  323.             m_pDevice->Clear(0L, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xff4444ff, 1.0f, 0L );
  324.  
  325.             m_cars[c].UpdateCameras();
  326.  
  327.             D3DXMATRIX world;
  328.             D3DXMatrixIdentity(&world);
  329.             m_pDevice->SetTransform(D3DTS_WORLD, &world);
  330.  
  331.             //Render track
  332.             m_pTrack->Render();
  333.  
  334.             //Render both cars
  335.             for(int i=0;i<m_cars.size();i++)
  336.                 m_cars[i].Render();
  337.         }
  338.  
  339.         // End the scene.
  340.         m_pDevice->EndScene();
  341.         m_pDevice->Present(0, 0, 0, 0);
  342.     }
  343.  
  344.     return S_OK;
  345. }
  346.  
  347. HRESULT APPLICATION::Cleanup()
  348. {
  349.     try
  350.     {
  351.         UnloadObjectResources();
  352.  
  353.         if(m_pTrack != NULL)m_pTrack->Release();
  354.  
  355.         m_pFont->Release();
  356.         m_pDevice->Release();
  357.  
  358.         debug.Print("Application terminated");
  359.     }
  360.     catch(...){}
  361.  
  362.     return S_OK;
  363. }
  364.  
  365. HRESULT APPLICATION::Quit()
  366. {
  367.     ::DestroyWindow(m_mainWindow);
  368.     ::PostQuitMessage(0);
  369.     return S_OK;
  370. }